home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / varie / uae-0_64.lha / uae-0.6.4 / src / autoconf.c < prev    next >
C/C++ Source or Header  |  1996-09-02  |  7KB  |  351 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * AutoConfig devices
  5.   *
  6.   * (c) 1995 Bernd Schmidt
  7.   * (c) 1996 Ed Hanway
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12.  
  13. #include "config.h"
  14. #include "options.h"
  15. #include "memory.h"
  16. #include "custom.h"
  17. #include "newcpu.h"
  18. #include "disk.h"
  19. #include "xwin.h"
  20. #include "autoconf.h"
  21.  
  22. static struct {
  23.     CPTR libbase;
  24.     TrapFunction functions[300]; /* I don't think any library has more than 300 functions */
  25. } libpatches[20];
  26. static int n_libpatches = 0;
  27.  
  28. ULONG Call68k_retaddr(CPTR address, int saveregs, CPTR retaddr)
  29. {
  30.     ULONG retval;
  31.     CPTR oldpc = m68k_getpc();
  32.  
  33.     struct regstruct backup_regs;
  34.     if (saveregs)
  35.     backup_regs = regs;
  36.     regs.a[7] -= 4;
  37.     put_long (regs.a[7], retaddr);
  38.     m68k_setpc(address);
  39.     m68k_go(0);
  40.     retval = regs.d[0];
  41.     if (saveregs)
  42.     regs = backup_regs;
  43.     m68k_setpc(oldpc);
  44.     return retval;
  45. }
  46.  
  47. ULONG Call68k(CPTR address, int saveregs)
  48. {
  49.     return Call68k_retaddr(address, saveregs, 0xF0FFF0);
  50. }
  51.  
  52. ULONG CallLib(CPTR base, WORD offset)
  53. {
  54.     int i;    
  55.     CPTR olda6 = regs.a[6];
  56.     ULONG retval;
  57.  
  58.     for (i = 0; i < n_libpatches; i++) {
  59.     if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL)
  60.         return (*libpatches[i].functions[-offset/6])();
  61.     }
  62.     
  63.     regs.a[6] = base;
  64.     retval = Call68k(base + offset, 1);
  65.     regs.a[6] = olda6;
  66.     return retval;
  67. }
  68.  
  69. /* @$%&§ compiler bugs */
  70. static volatile int four = 4;
  71.  
  72. CPTR libemu_InstallFunctionFlags(TrapFunction f, CPTR libbase, int offset,
  73.                  int flags)
  74. {
  75.     int i;
  76.     CPTR retval;
  77.     CPTR execbase = get_long(four);
  78.     ULONG addr = here();
  79.     calltrap2(deftrap2(f, flags));
  80.     dw(RTS);
  81.     
  82.     regs.a[1] = libbase;
  83.     regs.a[0] = offset;
  84.     regs.d[0] = addr;
  85.     retval = CallLib(execbase, -420);
  86.     for (i = 0; i < n_libpatches; i++) {
  87.     if (libpatches[i].libbase == libbase)
  88.         break;
  89.     }
  90.     if (i == n_libpatches) {
  91.     int j;
  92.     libpatches[i].libbase = libbase;
  93.     for (j = 0; j < 300; j++)
  94.         libpatches[i].functions[j] = NULL;
  95.     n_libpatches++;
  96.     }
  97.     libpatches[i].functions[-offset/6] = f;
  98.     return retval;
  99. }
  100.  
  101. CPTR libemu_InstallFunction(TrapFunction f, CPTR libbase, int offset)
  102. {
  103.     return libemu_InstallFunctionFlags(f, libbase, offset, 0);
  104. }
  105.  
  106. /* Commonly used autoconfig strings */
  107.  
  108. CPTR EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion;
  109. CPTR EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36;
  110. CPTR EXPANSION_bootcode;
  111.  
  112. static int current_deviceno = 0;
  113.  
  114. int get_new_device(char **devname, CPTR *devname_amiga)
  115. {
  116.     char buffer[80];
  117.     
  118.     sprintf(buffer,"UAE%d", current_deviceno);
  119.  
  120.     *devname_amiga = ds(*devname = strdup(buffer));
  121.     return current_deviceno++;
  122. }
  123.  
  124. /* ROM tag area memory access */
  125.  
  126. static UBYTE rtarea[65536];
  127.  
  128. static ULONG rtarea_lget(CPTR) REGPARAM;
  129. static UWORD rtarea_wget(CPTR) REGPARAM;
  130. static UBYTE rtarea_bget(CPTR) REGPARAM;
  131. static void  rtarea_lput(CPTR, ULONG) REGPARAM;
  132. static void  rtarea_wput(CPTR, UWORD) REGPARAM;
  133. static void  rtarea_bput(CPTR, UBYTE) REGPARAM;
  134. static UBYTE *rtarea_xlate(CPTR) REGPARAM;
  135.  
  136. addrbank rtarea_bank = {
  137.     rtarea_lget, rtarea_wget,
  138.     rtarea_lget, rtarea_wget, rtarea_bget,
  139.     rtarea_lput, rtarea_wput, rtarea_bput,
  140.     rtarea_xlate, default_check
  141. };
  142.  
  143. UBYTE *rtarea_xlate(CPTR addr)
  144. {
  145.     addr &= 0xFFFF;
  146.     return rtarea + addr;
  147. }
  148.  
  149. ULONG rtarea_lget(CPTR addr)
  150. {
  151.     addr &= 0xFFFF;
  152.     return (ULONG)(rtarea_wget(addr) << 16) + rtarea_wget(addr+2);
  153. }
  154.  
  155. UWORD rtarea_wget(CPTR addr)
  156. {
  157.     addr &= 0xFFFF;
  158.     return (rtarea[addr]<<8) + rtarea[addr+1];
  159. }
  160.  
  161. UBYTE rtarea_bget(CPTR addr)
  162. {
  163.     UWORD data;
  164.     addr &= 0xFFFF;
  165.     return rtarea[addr];
  166. }
  167.  
  168. void rtarea_lput(CPTR addr, ULONG value) { }
  169. void rtarea_bput(CPTR addr, UBYTE value) { }
  170.  
  171. /* Don't start at 0 -- can get bogus writes there. */
  172. static ULONG trap_base_addr = 0x00F00180;
  173.  
  174. /* We'll need a lot of these. */
  175. TrapFunction traps[16384];
  176. char trapmode[16384];
  177.  
  178. static int max_trap = 0;
  179.  
  180. int lasttrap;
  181.  
  182. void do_emultrap(int tr)
  183. {
  184.     struct regstruct backup_regs;
  185.     ULONG retval;
  186.  
  187.     if ((trapmode[tr] & 1) == 0)
  188.     backup_regs = regs;
  189.     retval = (*traps[tr])();
  190.     if ((trapmode[tr] & 1) == 0)
  191.         regs = backup_regs;
  192.     if ((trapmode[tr] & 2) == 0)
  193.     regs.d[0] = retval;
  194. }
  195.  
  196. void rtarea_wput(CPTR addr, UWORD value) 
  197. {
  198.     /* Save all registers */
  199.     struct regstruct backup_regs;
  200.     ULONG retval = 0;
  201.     ULONG func = ((addr  - trap_base_addr) & 0xFFFF) >> 1;
  202.  
  203.     if (func == 0) {
  204.     lasttrap = get_long(regs.a[7]);
  205.     regs.a[7] += 4;
  206.     regs.spcflags |= SPCFLAG_EMULTRAP;
  207.     return;
  208.     }
  209.     
  210.     backup_regs = regs;
  211.     if(func < max_trap) {
  212.     retval = (*traps[func])();
  213.     } else {
  214.     fprintf(stderr, "illegal emulator trap\n");
  215.     }
  216.     regs = backup_regs;
  217.     regs.d[0] = retval;
  218. }
  219.  
  220. /* some quick & dirty code to fill in the rt area and save me a lot of
  221.  * scratch paper
  222.  */
  223.  
  224. static int rt_addr = 0;
  225. static int rt_straddr = 0xFF00 - 2;
  226.  
  227. ULONG addr(int ptr)
  228. {
  229.     return (ULONG)ptr + 0x00F00000;
  230. }
  231.  
  232. void dw(UWORD data)
  233. {
  234.     rtarea[rt_addr++] = data >> 8;
  235.     rtarea[rt_addr++] = data;
  236. }
  237.  
  238. void dl(ULONG data)
  239. {
  240.     rtarea[rt_addr++] = data >> 24;
  241.     rtarea[rt_addr++] = data >> 16;
  242.     rtarea[rt_addr++] = data >> 8;
  243.     rtarea[rt_addr++] = data;
  244. }
  245.  
  246. /* store strings starting at the end of the rt area and working
  247.  * backward.  store pointer at current address
  248.  */
  249.  
  250. ULONG ds(char *str)
  251. {
  252.     int len = strlen(str) + 1;
  253.  
  254.     rt_straddr -= len;
  255.     strcpy(rtarea + rt_straddr, str);
  256.     
  257.     return addr(rt_straddr);
  258. }
  259.  
  260. void calltrap2(ULONG n)
  261. {
  262.     dw(0x4878); /* PEA.L n.w */
  263.     dw(n);
  264.     /* Call trap #0 is reserved for this */
  265.     dw(0x33C0);    /* MOVE.W D0,abs32 */
  266.     dl(trap_base_addr);
  267. }
  268.  
  269. void calltrap(ULONG n)
  270. {
  271. #if 1
  272.     dw(0x33C0);    /* MOVE.W D0,abs32 */
  273.     dl(n*2 + trap_base_addr);
  274. #else
  275.     calltrap2(n);
  276. #endif
  277. }
  278.  
  279. void org(ULONG a)
  280. {
  281.     rt_addr = a - 0x00F00000;
  282. }
  283.  
  284. ULONG here(void)
  285. {
  286.     return addr(rt_addr);
  287. }
  288.  
  289. int deftrap(TrapFunction func)
  290. {
  291.     int num = max_trap++;
  292.     traps[num] = func;
  293.     trapmode[num] = 0;
  294.     return num;
  295. }
  296.  
  297. int deftrap2(TrapFunction func, int mode)
  298. {
  299.     int num = max_trap++;
  300.     traps[num] = func;
  301.     trapmode[num] = mode;
  302.     return num;
  303. }
  304.  
  305. void align(int b)
  306. {
  307.     rt_addr = (rt_addr + (b-1)) & ~(b-1);
  308. }
  309.  
  310. static ULONG bootcode(void)
  311. {
  312.     regs.a[1] = EXPANSION_doslibname;
  313.     regs.d[0] = CallLib (regs.a[6], -96); /* FindResident() */
  314.     regs.a[0] = get_long(regs.d[0]+22); /* get dos.library rt_init */
  315.     return regs.a[0];
  316. }
  317.  
  318. void rtarea_init()
  319. {
  320.     ULONG a;
  321.     char uaever[100];
  322.     sprintf(uaever, "uae-%d.%d.%d", (version / 100) % 10, (version / 10) % 10, (version / 1) % 10);
  323.  
  324.     EXPANSION_uaeversion = ds(uaever);
  325.     EXPANSION_explibname = ds("expansion.library");
  326.     EXPANSION_doslibname = ds("dos.library");
  327.     EXPANSION_uaedevname = ds("uae.device");
  328.  
  329.     deftrap(NULL); /* Generic emulator trap */
  330.     lasttrap = 0;
  331.  
  332.     align(4);
  333.     EXPANSION_bootcode = here();
  334.     calltrap2(deftrap2(bootcode, 1));
  335.     dw(0x2040);            /* move.l d0,a0 */
  336.     dw(0x4e90);                 /* jsr (a0) */
  337.     dw(RTS);
  338.  
  339.     a = here();
  340.  
  341.     /* Idle task */
  342.     org(0xF0FFF0 - 4);
  343.     dw(0x4E72); dw (0x2000); /* STOP 0x2000 */
  344.     
  345.     /* Standard "return from 68k mode" trap */
  346.     /*org(0xF0FFF0); */
  347.     calltrap2(0);
  348.     dw(RTS);
  349.     org(a);
  350. }
  351.